/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#ifndef VIEW_H
#define VIEW_H

#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif


#include "propertyBag.h"
class Graph;

class Label {
	string text;
	string alignment;
	float x, y;
};

class Clickable {
public:
    float x, y;
    float w, h;
    bool selected;
    bool visible;
    bool hovered;
    Clickable() { x=y=0; w=h=0; selected=visible=hovered=false;}
    virtual ~Clickable() {};
    virtual void draw() = 0;
    bool isSelected() {return selected;}
    virtual void setSelected(bool value) {selected = value;}
    virtual bool encloses(float px, float py);
    virtual bool isVisible() { return visible; }
    virtual void setVisible(bool value) { visible = value; }
    virtual void setSize(float w, float h) { this->w = w; this->h = h; }
    virtual void getSize(float &w, float &h) { w = this->w; h = this->h; }
    virtual void setLocation(float x, float y) { this->x = x; this->y = y; }
    virtual void getLocation(float &x, float &y) { x = this->x; y = this->y; }
    virtual void click(float , float , int  ) {}
    virtual void drag(float , float , float dx, float dy, int ) { x+=dx; y+=dy;}
    virtual void mouseMove(float, float , float , float , int ) { }
    virtual void release(float , float, int ) {}
};

class Controller;

// TODO
// Improve the visual mapping:
// Should these be in the controller?
// GetNormalizedValue : returns value in (0,1)
// GetPropertyAsFloat
// GetPropertyAsInt
// stringToInt // requires access to all
// getMappedColor
// getColor(value)


class View:public Clickable, public PropertyBag {
protected:
    enum {
        NONE,
        MOVE,
        RESIZE,
        DRAG,
				PAN,
				ZOOM
    };
    int dragMode;
    GLint V[4];
    bool zoomable;

    string creator;
    vector<Clickable *> viewClickables;
    vector<Clickable *> windowClickables;
    float marginTop, marginLeft, marginRight, marginBottom;
    float margins[4];
    float zoom;
    float panx, pany;
    int clickStatus; // Tells what happened on a click event


public:

    float titleHeight;
    bool bTransparent;
    bool enableDefaultSelection;
    bool hoveredTitle;

    float fColor_back;
    float fColor_backTrans;
    float fColor_backTrans2;
    float fColor_front;

    // Font
    string currentFont;
    int currentFontSize;
    string currentFontStyle;

    View(const char *type, const char *name);
    virtual ~View();
    void setCreator(string c);
    string getCreator();

    void setMargins(float l, float r, float t, float b);

    virtual void draw();
    virtual void drawBackground();
    virtual void drawTitle();
    virtual void render();

    bool isZoomable() {return zoomable;}
    void setZoomable(bool value) {zoomable = value;}
    int getClickStatus() { return clickStatus;}
    virtual bool isVisible();
	
		// Events
    virtual void click(float x, float y, int modifiers);
    virtual void release(float x, float y,int modifiers);
    virtual void drag(float px, float py, float dx, float dy, int modifiers = 0);
    virtual void mouseMove(float px, float py, float dx, float dy, int modifiers = 0);
    virtual void tic();
    virtual void update(string property);

    virtual bool encloses(float px, float py);
    void getPixel(float &x, float &y);
    void getPixelWindow(float &x, float &y);


    // Conversion of coordinates
    void toWindow(float wx, float wy, float &rx, float &ry);
    void toWindowDisplacement(float wx, float wy, float &rx, float &ry);
    void toView(float wx, float wy, float &rx, float &ry);
    void toViewDisplacement(float wx, float wy, float &rx, float &ry);

    void toRelative(float wx, float wy, float &rx, float &ry);   // Deprecated
    void toRelativeDisplacement(float wx, float wy, float &rx, float &ry);   // Deprecated

		// Selection
    float selectionX, selectionY;
    float selectionWidth, selectionHeight;
    bool inSelection(float x, float y);
    bool intersectsSelection(float x1, float y1, float x2, float y2);
    bool intersectLineBox(float x1, float y1, float x2, float y2, float boxX, float boxY, float boxW, float boxH);

		// in-view widgets
    void addViewClickable(Clickable *c);
    void addWindowClickable(Clickable *c);
    void deleteClickable(Clickable * c);

    int selectionMarker;
    void setSelectionMarker(int selection);
    void setDefaultSelection(bool value) {
        enableDefaultSelection = value;
    }
    void addSelectionWidget();
    void addCloseButton();
    void addTransparentButton();
    void addExpandButton();
    void addCustomWidget(Clickable *c);

    Controller *controller;

    Graph *graph;
    virtual void setGraph(Graph *g);

    virtual void clearSelection(int selection);
    bool performingSelection;

    bool validGeometryCache;
    void invalidateGeometryCache();

    // Geometric utilities
    float pixx, pixy;
    void updatePixelScale();
    // Returns the appropriate amount in x- and y- coordinates corresponding to the desired pixels
    virtual void textBounds(float &w, float &h, const char *text, const char *font = "Arial", int fontsize = 10);
    virtual inline float xpixels(float pixels) {
        return pixels*pixx;
    }
    virtual inline float ypixels(float pixels) {
        return pixels*pixy;
    }

    // I/O
    virtual void save(FILE *) {}
    virtual void load(vector<string> ) {}


    // Property Helper Functions
    string PROPERTY(string property);

    void getAsColor(PropertyBag *bag, string property, string colormap, float *rgb);
    void getColor(string colormap, float f, float *rgb); // retrieves the color associated with property
    void getColor(string colormap, int i, float *rgb); // retrieves the color associated with property
    void getMinMax(string property, float &minv, float &maxv);
		bool getMinMaxLog(string property, float &minlog, float &maxlog);
		bool getMinMaxLog(vector<float> values, float &minlog, float &maxlog);
		void getTics(string property, int numTics, vector<float> &tics, vector<string> &values);
		void getLogTics(string property, int numTics, vector<float> &tics, vector<string> &values);
		void getTics(Interval interval, int numTics, vector<float> &tics, vector<string> &values);
		void getLogTics(Interval interval, int numTics, vector<float> &tics, vector<string> &values);
		vector<string> parseMultiProperty(string props);

    // Text
    void setFont(string font, int size, string style);
    void renderText(float x, float y, const char * text, string alignment = "left", string alignmenty = "bottom");
    void renderTextBox(float x, float y, const char * text, string alignment = "left", string alignmenty = "bottom", float marginx = 0, float marginy = 0);
    void renderRoundTextBox(float x, float y, const char * text, string alignmentx, string alignmenty, float marginx, float marginy, float opacity=1.0);
    void getTextBounds(float &textwidth, float &textheight, const char * text);
    void getTextBox(float &x, float &y,  float &w, float &h, const char *text, string alignment ="left", string alignmenty="bottom");
		string getCurrentFont() {
			return currentFont;
		}
		int getCurrentFontSize() {
			return currentFontSize;
		}
	
		void updateFont();
	
    // View
    void resetView();

    // Selection
    void getSelectionColor(int selected, float *rgb);

    // Color
    virtual void colorUpdated();
    virtual void layoutUpdated();
	
	//	Selection of nodes and edges
	// selectionId = -1 indicates unselection
		void selectElement(PropertyBag *element, int selectionId);
		void selectElements(vector<PropertyBag *>&elements, int selectionId);
};






#endif
